---
sidebar_position: 5
title: Guide - Headers
sidebar_label: Headers
---

# Headers

In HTTP requests, headers are a crucial component, carrying additional information between the client and the server.
They can be used for authentication, content type specification, caching control, and more. Hyper-fetch provides a
flexible and powerful way to manage headers for your requests.

---

:::secondary What you'll learn

1. How to set **global headers** on the Hyper-fetch client.
2. How to set **static headers** when creating a request.
3. How to add or override headers **dynamically** before sending a request.
4. How to set headers for a **single specific execution** of a request.
5. Understanding the **order of merging** for all header types.
6. What are the **adapter limitations** regarding headers.

:::

---

## Setting Headers

Hyper-fetch offers multiple levels for setting headers, giving you fine-grained control over how they are applied.
Headers are merged in a specific order of precedence, allowing you to set defaults and override them when needed.

### 1. Global Headers

You can set headers on the `client` instance. These headers will be automatically included in **every request** created
by that client. This is useful for headers that are common to all API calls, like `Accept` or `Authorization` tokens.

```ts
// Let's create a new client from the base one, with added global headers
const apiClient = client.new({
  headers: {
    Accept: "application/json",
    Authorization: "Bearer your-static-token",
  },
});

// A request created with this client will inherit its headers
const getUsers = apiClient.createRequest()({
  endpoint: "/users",
});

// highlight-next-line
console.log("Inherited headers:", getUsers.headers);

const getProducts = apiClient.createRequest()({
  endpoint: "/products",
});

// highlight-next-line
console.log("All requests from apiClient have these headers:", getProducts.headers);
```

### 2. Per-Request Headers

For more granular control, you can set headers on a per-request basis. These headers are merged with global client
headers, allowing you to add new ones or override the global settings for a specific request.

#### Static Headers

If a request always requires specific headers, you can define them when creating it. These static headers are merged
with global headers, with request-specific headers taking precedence in case of conflicts.

```ts
const apiClient = client.new({
  headers: {
    Accept: "application/json",
  },
});

// We can add more headers or override the client's headers
const getUsers = apiClient.createRequest()({
  endpoint: "/users",
  // highlight-start
  headers: {
    "X-Custom-Header": "my-value",
    Accept: "application/xml", // This will override the client's Accept header
  },
  // highlight-end
});

// The headers are now a combination of client and request headers
console.log("Merged static headers:", getUsers.headers);
```

#### Dynamic Headers

For headers that change at runtime, like a session-based authentication token, you can use the `.setHeaders()` method.
This method merges the new headers with any existing ones on the request instance.

```ts
const getUser = client.createRequest()({
  endpoint: "/users/1",
});

// A function that provides the latest auth token
const getAuthToken = () => "Bearer new-secret-token";

// Use .setHeaders() to apply the dynamic header
// highlight-next-line
const requestWithAuth = getUser.setHeaders({
  Authorization: getAuthToken(),
});

console.log("Request with dynamic header:", requestWithAuth.headers);
```

#### One-Time Headers

You can also provide headers directly to the `.send()` method. These headers are used only for that specific request
execution and have the highest precedence, overriding any headers defined on the client or the request instance.

```ts
const updateUser = client.createRequest()({
  endpoint: "/users/1",
  method: "PUT",
  headers: { "X-Static-Header": "some-value" },
});

// The 'send' method triggers the request with the one-time headers
// Note: for this example, we are just showing how to pass headers.
updateUser.send({
  // highlight-start
  headers: {
    "X-Request-ID": "abc-123",
    "X-Static-Header": "overridden-value", // This overrides the static header for this call
  },
  // highlight-end
});

// The headers on the 'updateUser' instance itself are not changed by .send()
console.log("Original request headers:", updateUser.headers);
```

### Headers Precedence

Hyper-fetch merges headers from different sources in a specific order. Each subsequent level overrides the previous one
in case of duplicate header keys:

1.  **Client Headers**: The base level, providing default headers for all requests.
2.  **Request Static Headers**: Headers defined on the request instance, overriding client headers.
3.  **Request Dynamic Headers (`.setHeaders`)**: Headers set with `.setHeaders()`, overriding static and client headers.
4.  **Send Method Headers (`.send`)**: One-time headers with the highest precedence, overriding all others for a single
    execution.

---

:::warning Adapter Compatibility

It's important to remember that not all adapters will use headers. For instance, adapters for services that don't use
the HTTP protocol, like `@hyper-fetch/firebase`, will ignore them. Always check the documentation for the adapter you're
using to see if it supports headers.

:::

---

:::success Congratulations!

You now know how to manage headers in Hyper-fetch like a pro!

- You can set **global headers** on the client for all requests.
- You can define **static headers** on a request for consistent values.
- You can use `.setHeaders()` to apply **dynamic headers** at runtime.
- You can pass **one-time headers** directly to `.send()` for specific calls.
- You understand the **precedence rules** for header merging.
- You are aware of **adapter limitations** regarding headers.

:::
